// Tierless
// Copyright © 2010 Alphora
// This file is licensed under a modified BSD-license (see tierless_license.txt).
using System.Runtime.Serialization;

using Tierless.Framework.Entities;
using Tierless.Framework.EntityTypes;

namespace Tierless.Framework.Data
{
	/// <summary>
	/// Models a parameter associated with a specific entity type.
	/// </summary>
	[DataContract]
	public class EntityParameter : NamedEntityTypeObject
	{
		/// <summary>
		/// Constructs a new instance of an entity parameter.
		/// </summary>
		/// <param name="name">The name of the parameter.</param>
		/// <param name="tempValue">The value of the parameter.</param>
		public EntityParameter(string name, object tempValue)
			: base(name)
		{
			_value = tempValue;
		}

		/// <summary>
		/// Constructs a new instance of an entity parameter.
		/// </summary>
		/// <param name="entityName">The name of the entity type to which the parameter applies.</param>
		/// <param name="parameterName">The name of the parameter.</param>
		/// <param name="tempValue">The value of the parameter.</param>
		public EntityParameter(string entityName, string parameterName, object tempValue)
			: this(parameterName, tempValue)
		{
			EntityName = entityName;
		}

		private object _value;

		/// <summary>
		/// Gets or sets the value of the parameter.
		/// </summary>
		[DataMember]
		public object Value
		{
			get { return _value; }
			set { _value = value; }
		}

		/// <summary>
		/// Gets or sets the name of the entity type to which the parameter applies.
		/// </summary>
		[DataMember]
		public string EntityName { get; set; }

		/// <summary>
		/// Returns a description of the entity parameter.
		/// </summary>
		/// <returns>A string representation of the entity parameter.</returns>
		public override string ToString()
		{
			return string.Format("EntityParameter: EntityName={2}, Name={0}, Value={1};", Name, Value, EntityName ?? "Not specified");
		}

		/// <summary>
		/// Returns true if the given object is equal to this entity parameter.
		/// </summary>
		/// <param name="obj">The object to be compared.</param>
		/// <returns>True if the object is equal to this entity parameter, false otherwise.</returns>
		/// <remarks>
		/// This method performs a value-based comparison, meaning that two different instances of
		/// the EntityParameter class can be equal if they have the same EntityName, Name, and Value.
		/// </remarks>
		public override bool Equals(object obj)
		{
			var other = obj as EntityParameter;
			return (other != null)
				&& ((EntityName == null) == (other.EntityName == null))
				&& ((EntityName == null) || (EntityName == other.EntityName))
				&& ((Name == null) == (other.Name == null))
				&& ((Name == null) || (Name == other.Name))
				&& ((_value == null) == (other._value == null))
				&& ((_value == null) || _value.Equals(other._value));
		}

		/// <summary>
		/// Gets the hash code for this instance.
		/// </summary>
		/// <returns>The hash code for this instance.</returns>
		/// <remarks>
		/// This method computes a hash code that is consistent with the value-based comparison semantics
		/// of the <see cref="Equals"/> method override on this class. This means that two different instances
		/// will have the same hashcode if they have the same EntityName, Name, and Value.
		/// </remarks>
		public override int GetHashCode()
		{
			var code = base.GetHashCode();

			if (EntityName != null)
				code = code * 83 + EntityName.GetHashCode();

			if (Name != null)
				code = code * 83 + Name.GetHashCode();

			if (_value != null)
				code = code * 83 + _value.GetHashCode();

			return code;
		}
	}
}